package hmac

import (
	"crypto/rand"
	"encoding/pem"
	"errors"
	"gitee.com/zackeus/go-boot/tools/errorx"
	"github.com/go-jose/go-jose/v4"
)

// GenerateHMAC 生成 HMAC 密钥
func GenerateHMAC(alg jose.SignatureAlgorithm) ([]byte, error) {
	/* 默认 HS256 */
	keyLen := 32

	switch alg {
	case jose.HS384:
		keyLen = 48
	case jose.HS512:
		keyLen = 64
	}

	key := make([]byte, keyLen)
	_, err := rand.Read(key)
	if err != nil {
		return nil, errorx.Wrap(err, "生成 HMAC 密钥失败")
	}

	return key, nil
}

// GenerateHMACPem 生成 HMAC 密钥
func GenerateHMACPem(alg jose.SignatureAlgorithm) ([]byte, error) {
	key, err := GenerateHMAC(alg)
	if err != nil {
		return nil, err
	}

	/* HMAC 密钥通常也存储为 PEM 格式，类型可以自定义为 "HMAC KEY" */
	hmacPEM := pem.EncodeToMemory(&pem.Block{
		Type:  "HMAC KEY",
		Bytes: key,
	})
	return hmacPEM, nil
}

// LoadHMACKey 从 PEM 格式数据中加载 HMAC 密钥
// pemData 是 GenerateHMACPem 生成的 PEM 字节
func LoadHMACKey(pemData []byte) ([]byte, error) {
	// 解码 PEM 数据
	block, _ := pem.Decode(pemData)
	if block == nil {
		return nil, errors.New("无效的 PEM 数据")
	}

	// 验证 PEM 块类型是否匹配
	if block.Type != "HMAC KEY" {
		return nil, errors.New("PEM 块类型不匹配，期望 HMAC KEY")
	}
	// 返回原始密钥字节
	return block.Bytes, nil
}
